# src/api/app.py
import asyncio
import logging
from typing import Dict, Any
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
import json

from src.core.graph_manager import GraphManager
from src.tools.mcp_client import create_mcp_connection
from config import config

# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Initialize FastAPI app
app = FastAPI(title="Agentic Jira API", version="1.0.0")

# Add CORS middleware to allow frontend connections
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000", "http://localhost:8080"],  # Adjust as needed
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Pydantic models for request/response
class MessageRequest(BaseModel):
    message: str

class MessageResponse(BaseModel):
    success: bool
    message: str

class McpTestResponse(BaseModel):
    success: bool
    message: str
    tools: list = []

class ClearConversationResponse(BaseModel):
    success: bool
    message: str

# Initialize components
graph_manager = GraphManager()
graph = graph_manager.compile()

@app.get("/")
async def root():
    """Root endpoint for health check"""
    return {"message": "Agentic Jira API is running"}

@app.post("/api/send-message", response_model=MessageResponse)
async def send_message(request: MessageRequest):
    """
    Send a message to the agent and get a response
    """
    try:
        logger.info(f"Received message: {request.message}")
        
        # Process user input through the graph
        from langchain_core.messages import HumanMessage
        
        inputs = {
            "messages": [HumanMessage(content=request.message)],
            "next": "",
            "rag_needed": False,
            "rag_response": "",
            "tool_response": "",
            "agent_action": "",
            "agent_response": "",
            "current_agent": ""
        }
        
        logger.info("Processing input through agent graph")
        result = graph.invoke(inputs)
        logger.info("Agent graph processing completed")
        
        # Extract and return the final response
        messages = result["messages"]
        if messages:
            final_message = messages[-1].content if hasattr(messages[-1], 'content') else str(messages[-1])
            logger.info(f"Agent response: {final_message}")
            return MessageResponse(success=True, message=final_message)
        else:
            logger.warning("No response generated by agents")
            return MessageResponse(success=False, message="No response generated.")
            
    except Exception as e:
        logger.error(f"Error processing message: {str(e)}", exc_info=True)
        return MessageResponse(success=False, message=f"Error: {str(e)}")

@app.post("/api/test-mcp", response_model=McpTestResponse)
async def test_mcp_connection():
    """
    Test MCP server connection and list tools
    """
    try:
        logger.info("Testing MCP connection")
        
        # Get MCP configuration from config module
        server_url = config.mcp_url
        api_key = config.mcp_api_key or None  # Use API key if available
        
        # Using new MCP client
        connector = await create_mcp_connection(
            server_url=server_url,
            api_key=api_key
        )
        
        # Test initialization
        tools_result = await connector.list_tools()
        
        # Close connection
        await connector.close()
        
        tools_list = []
        if 'tools' in tools_result:
            tools_list = [{"name": tool.get("name", ""), "description": tool.get("description", "")} 
                         for tool in tools_result['tools']]
        
        return McpTestResponse(
            success=True,
            message="MCP connection test completed successfully",
            tools=tools_list
        )
        
    except Exception as e:
        logger.error(f"Error testing MCP connection: {str(e)}", exc_info=True)
        return McpTestResponse(
            success=False,
            message=f"Error testing MCP connection: {str(e)}",
            tools=[]
        )

@app.post("/api/clear-conversation", response_model=ClearConversationResponse)
async def clear_conversation():
    """
    Clear conversation history (placeholder implementation)
    """
    try:
        # In a real implementation, you might want to reset the graph state
        # For now, we'll just return a success message
        return ClearConversationResponse(
            success=True,
            message="Conversation history cleared successfully"
        )
    except Exception as e:
        logger.error(f"Error clearing conversation: {str(e)}", exc_info=True)
        return ClearConversationResponse(
            success=False,
            message=f"Error clearing conversation: {str(e)}"
        )

@app.post("/api/exit", response_model=MessageResponse)
async def exit_application():
    """
    Exit the application (placeholder implementation)
    """
    try:
        # In a web context, we can't actually exit the server
        # We'll just return a message indicating the intent
        return MessageResponse(
            success=True,
            message="Exit command received. In a web context, this would close the application."
        )
    except Exception as e:
        logger.error(f"Error processing exit command: {str(e)}", exc_info=True)
        return MessageResponse(
            success=False,
            message=f"Error processing exit command: {str(e)}"
        )

# For running with uvicorn
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)